/*
 * Copyright (c) 2019-2029, <a href="https://wwww.intellijboy.cn">https://wwww.intellijboy.cn</a> (liuburu@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * <a href="https://www.apache.org/licenses/LICENSE-2.0">https://www.apache.org/licenses/LICENSE-2.0</a>
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package open.intellijboy.framework.core.util;

import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.concurrent.TimeUnit;

/**
 * 框架通用工具方法
 *
 * @author intellijboy
 * @date 2023/9/24
 * @since 1.0
 */
public class DevToolUtils {
    private static final Path BROWSER_OPEN_FLAG_FILE_PATH = Paths.get(System.getProperty("user.home"), ".browser_open_flag");

    /**
     * 打开浏览器访问指定 URL
     *
     * @param url 目标地址
     * @throws IOException 如果无法打开浏览器或写入标志文件
     */
    public static void browseOpen(String url) throws IOException {
        if (!Desktop.isDesktopSupported() || !Desktop.getDesktop()
                                                     .isSupported(Desktop.Action.BROWSE)) {
            fallbackOpen(url);
        } else {
            try {
                Desktop.getDesktop()
                       .browse(URI.create(url));
            } catch (IOException | RuntimeException e) {
                // 桌面 API 失败，降级
                fallbackOpen(url);
            }
        }

        // 写入打开时间戳
        try {
            if (!Files.exists(BROWSER_OPEN_FLAG_FILE_PATH)) {
                Files.createFile(BROWSER_OPEN_FLAG_FILE_PATH);
            }
            Files.writeString(BROWSER_OPEN_FLAG_FILE_PATH, String.valueOf(System.currentTimeMillis()),
                    StandardCharsets.UTF_8, StandardOpenOption.TRUNCATE_EXISTING);
        } catch (IOException ioEx) {
            System.err.println("无法写入浏览器打开标志文件: " + ioEx.getMessage());
        }
    }

    /**
     * 降级方案：使用 ProcessBuilder 启动浏览器
     */
    private static void fallbackOpen(String url) throws IOException {
        String os = System.getProperty("os.name")
                          .toLowerCase();
        ProcessBuilder pb;

        if (os.contains("win")) {
            pb = new ProcessBuilder("rundll32", "url.dll,FileProtocolHandler", url);
        } else if (os.contains("mac")) {
            pb = new ProcessBuilder("open", url);
        } else if (os.contains("nix") || os.contains("nux")) {
            String browser = findUnixBrowser();
            if (browser == null) {
                throw new IOException("无法找到可用的浏览器");
            }
            pb = new ProcessBuilder(browser, url);
        } else {
            throw new IOException("不支持的操作系统");
        }

        pb.inheritIO()
          .start(); // 可选：inheritIO 用于调试
    }

    /**
     * 查找 Linux 可用浏览器
     */
    private static String findUnixBrowser() {
        String[] browsers = {"xdg-open", "google-chrome", "firefox", "mozilla", "konqueror", "epiphany", "netscape"};
        for (String b : browsers) {
            try {
                if (new ProcessBuilder("which", b).start()
                                                  .waitFor() == 0) {
                    return b;
                }
            } catch (InterruptedException | IOException ignored) {
                // 继续尝试下一个
            }
        }
        return null;
    }

    /**
     * 是否近期流量拿起打开过
     *
     * @return 返回打开状态
     */
    public static boolean isRecentBrowserOpened() {
        File file = BROWSER_OPEN_FLAG_FILE_PATH.toFile();
        if (!file.exists()) {
            return false;
        }
        long diffInSeconds = TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - file.lastModified());
        // 1小内认为是近期打开过
        if (diffInSeconds < 3600) {
            return true;
        }
        return false;
    }
}
